# pip install zhipuai 请先在终端进行安装
import os
import sys

from zhipuai import ZhipuAI


glm4_chat_create_md = """
### client.chat.completions.create函数参数详解
&emsp;&emsp;在通过SDK调用模型的时候，chat.completions.create函数中的参数设置会直接决定最终模型运行模式、以及模型运行结果。因此在基础模型学习阶段，我们需要围绕chat.completions.create函数进行完整的参数解释。
- chat.completions.create函数必选参数
&emsp;&emsp;整体来看，GLM模型参数和GPT模型参数高度类似，并且通过观察不难发现，chat.completions.create函数有两个必选参数，其一是model，代表的含义是当前调用的模型。根据上一小节的介绍，目前可选的模型有两个，其一是GLM-3-Turbo、其二则是GLM-4；第二个参数则是messages，代表传输到模型内部的消息队列。messages参数是一个基本构成元素为字典的列表，其内每个字典都代表一条独立的消息，每个字典都包含两个键值（Key-value）对，其中第一个Key都是字符串role（角色）表示某条消息的作者，第二个key为content（内容）表示消息具体内容。更多关于message的参数设置方法稍后介绍，总的来看，这里的messages就可以简单理解为输入给模型的信息队列，而模型接收到message之后也会输出对应的回答信息，当然也是以message形式呈现：
&emsp;&emsp;接下来围绕chat.completions.create函数的全部参数进行解释：

| 参数名称       | 类型 | 是否必填   | 参数解释 |
| ----------- | ------- | ------------ | ------------------------------------------------------------ |
| model       | String           | 是   | 所要调用的模型编码                                           |
| messages    | List<Object>     | 是   | 调用语言模型时，将当前对话信息列表作为提示输入给模型， 按照 `{"role": "user", "content": "你好"}` 的json 数组形式进行传参； 可能的消息类型包括 System message、User message、Assistant message 和 Tool message。 |
| request_id  | String           | 否   | 由用户端传参，需保证唯一性；用于区分每次请求的唯一标识，用户端不传时平台会默认生成。 |
| do_sample   | Boolean          | 否   | do_sample 为 true 时启用采样策略，do_sample 为 false 时采样策略 temperature、top_p 将不生效 |
| stream      | Boolean          | 否   | 使用同步调用时，此参数应当设置为 Fasle 或者省略。表示模型生成完所有内容后一次性返回所有内容。如果设置为 True，模型将通过标准 Event Stream ，逐块返回模型生成内容。Event Stream 结束时会返回一条`data: [DONE]`消息。 |
| temperature | Float            | 否   | 采样温度，控制输出的随机性，必须为正数取值范围是：(0.0,1.0]，不能等于 0，默认值为 0.95,值越大，会使输出更随机，更具创造性；值越小，输出会更加稳定或确定建议您根据应用场景调整 top_p 或 temperature 参数，但不要同时调整两个参数 |
| top_p       | Float            | 否   | 用温度取样的另一种方法，称为核取样 取值范围是：`(0.0, 1.0)` 开区间，不能等于 0 或 1，默认值为 0.7 模型考虑具有 `top_p` 概率质量tokens的结果 例如：0.1 意味着模型解码器只考虑从前 10% 的概率的候选集中取tokens 建议您根据应用场景调整 `top_p` 或 `temperature` 参数，但不要同时调整两个参数 |
| max_tokens  | Integer          | 否   | 模型输出最大tokens                                           |
| stop        | List             | 否   | 模型在遇到stop所制定的字符时将停止生成，目前仅支持单个停止词，格式为`["stop_word1"]` |
| tools       | List             | 否   | 可供模型调用的工具列表,tools字段会计算 tokens ，同样受到tokens长度的限制 |
| type        | String           | 是   | 工具类型,目前支持`function`、`retrieval`、`web_search`       |
| function    | Object           | 是   | 仅当工具类型为`function`时补充                               |
| retrieval   | Object           |      | 仅当工具类型为`retrieval`时补充                              |
| web_search  | Object           |      | 仅当工具类型为`web_search`时补充，如果tools中存在类型retrieval，此时web_search不生效。 |
| tool_choice | String 或 Object | 否   | 用于控制模型是如何选择要调用的函数，仅当工具类型为function时补充。默认为auto，当前仅支持auto |

整体来看，GLM系列模型的参数结构并不如GPT系列模型复杂，在上述一系列参数中，temperature、tools两个参数是需要重点关注，并且之后会经常用到的两个参数。其中tools参数会涉及模型功能方面调整，例如可以通过tools参数设置来选择是否开启联网、或者查阅在线知识库文档、或者开启Function calling功能等，该参数的使用方法我们将在下一小节进行介绍。

- 经典问答
client = ZhipuAI(api_key=api_key) 
response_t01 = client.chat.completions.create(
    model="glm-4",  
    messages=[
        {"role": "user", "content": "请问什么是机器学习？"}
    ],
    temperature=0.1
)
"""


client = ZhipuAI(api_key=os.environ["ZHIPU_API_KEY"])

messages = [
    {
        "role": "system",
        "content": "你是一个资深编程专家，\n" + glm4_chat_create_md
    }
]


while True:
    inputStr = input("请输入指令:")
    # inputStr = ""
    #
    # print("请输入指令:")
    # objList = sys.stdin.readlines()
    # for obj in objList:
    #     if inputStr == '':
    #         inputStr += obj.strip()
    #     else:
    #         inputStr += "\n" + obj.strip()

    if inputStr == 'bye':
        break

    messages.append({
                "role": "user",
                "content": inputStr
            })

    response = client.chat.completions.create(
        model="glm-4",
        messages=messages,
        top_p=0.7,
        temperature=0.95,
        max_tokens=1024
    )

    print(response.choices[0].message.content)

    messages.append({
                "role": "assistant",
                "content": response.choices[0].message.content
            })
print("全部结束")

